//
//  QLayerBlending.m
//  ImageEffect
//
//  Created by lichq on 14-1-14.
//  Copyright (c) 2014年 lichq. All rights reserved.
//

#import "QLayerBlending.h"

@implementation QLayerBlending


#pragma mark - mixed Channel

unsigned char layerMultiply(unsigned char a, unsigned char b){
    return a * b / 255;
}

unsigned char layerDarken(unsigned char a, unsigned char b){
    return MIN(a, b);
}

unsigned char layerLighten(unsigned char a, unsigned char b){
    return MAX(a, b);
}

unsigned char layerBurn(unsigned char a, unsigned char b){
    return (b == 0) ? b : MAX( 0, (255 - ((255-a)<<8)/b) );
}

unsigned char layerDodge(unsigned char a, unsigned char b){
    return (b == 255) ? b :MIN(255, ((a<<8) / (255-b)));
}

unsigned char layerLinearBurn(unsigned char a, unsigned char b){
    return (a + b < 255) ? 0 : (a + b - 255);
}
unsigned char layerLinearDodge(unsigned char a, unsigned char b){
    return MIN(255,(a + b));
}

unsigned char layerScreen(unsigned char a, unsigned char b){
    return 255 - ( ((255-a)*(255-b))>> 8 );
}

unsigned char layerOverlay(unsigned char a, unsigned char b){
    return (b < 128) ? (2*a*b/255) : (255-2*(255-a)*(255-b)/255);
}

unsigned char layerSoftLight(unsigned char a, unsigned char b){
    return (b < 128) ? (2 * ((a>>1)+64) * (b/255) ) : (255 - (2 * (255 - ((a>>1)+64)) *(255-b)/255 ) );
}

unsigned char layerHardLight(unsigned char a, unsigned char b){
    return (a < 128) ? (2 * a * b / 255 ) : ( 255 - (2 * (255-a) * (255-b) / 255) );
}

unsigned char layerVividLight(unsigned char a, unsigned char b){
    return (b < 128) ?
//    (b==0 ? 2*b : MAX( 0, (255 - ( (255-a)<<8) / (2*b) ) ) ) : (2 *(b-128) == 255) ? (2 * (b-128)) : MIN(255, ( (a<<8) / (255-(2*(b-128))) ) );
    
    layerBurn(a, (2*b)) : layerDodge(a, (2*(b-128)));
}

unsigned char layerLinearLight(unsigned char a, unsigned char b){
    return MIN(255, MAX( 0, (b+2*a)-255 ) );
}

unsigned char layerPinLight(unsigned char a, unsigned char b){
    return MAX(0, MAX(2*a-255, MIN(b, 2*a)));
}

unsigned char layerHardMix(unsigned char a, unsigned char b){
//    return
    return layerVividLight(a, b) < 128 ? 0 : 255;
}


unsigned char layerDifference(unsigned char a, unsigned char b){
    return abs(a - b);
}


unsigned char layerExclusion(unsigned char a, unsigned char b){
    return a + b - 2*a*b/255;
}




#pragma mark - Mixed Pixel
unsigned char* mixedPixel_layerFun(unsigned char *imagePixel1, unsigned char *imagePixel2, int w, int h, unsigned char (*mixedChannel_layerFun)(unsigned char channel1, unsigned char channel2)){
    unsigned char *imagePixel = imagePixel1;
    long startByte = 0;
    
    for(int y = 0;y< h;y++)
    {
        for (int x = 0; x < w; x++)
        {
            startByte = (y * w + x) * 4;
            
            imagePixel[startByte] = mixedChannel_layerFun(imagePixel1[startByte], imagePixel2[startByte]);
            imagePixel[startByte+1] = mixedChannel_layerFun(imagePixel1[startByte+1], imagePixel2[startByte+1]);
            imagePixel[startByte+2] = mixedChannel_layerFun(imagePixel1[startByte+2], imagePixel2[startByte+2]);
            //            imagePixel[startByte+3] = imagePixel1[startByte+3] * imagePixel2[startByte+3] / 255;
        }
    }
    
    return imagePixel;
}

unsigned char* mixedPixel_layerMultiply(unsigned char *imagePixel1, unsigned char *imagePixel2, int w, int h){
    
    return mixedPixel_layerFun(imagePixel1, imagePixel2, w, h, layerMultiply);
    
    /*
    unsigned char *imagePixel = imagePixel1;
    long startByte = 0;
    
    for(int y = 0;y< h;y++)
    {
        for (int x = 0; x < w; x++)
        {
            startByte = (y * w + x) * 4;
            
            imagePixel[startByte] = mixedChannel_layerMultiply(imagePixel1[startByte], imagePixel2[startByte]);
            imagePixel[startByte+1] = mixedChannel_layerMultiply(imagePixel1[startByte+1], imagePixel2[startByte+1]);
            imagePixel[startByte+2] = mixedChannel_layerMultiply(imagePixel1[startByte+2], imagePixel2[startByte+2]);
            //            imagePixel[startByte+3] = imagePixel1[startByte+3] * imagePixel2[startByte+3] / 255;
        }
    }
    
    return imagePixel;
    */
}

unsigned char* mixedPixel_layerDarken(unsigned char *imagePixel1, unsigned char *imagePixel2, int w, int h){
    
    return mixedPixel_layerFun(imagePixel1, imagePixel2, w, h, layerDarken);
    
}

@end
